import asyncio
import threading
from functools import partial

from loguru import logger

from common import config, utils
from core.dashboard import dashboard
from core.session import Session
from core.website import website


class Robot:
    def __init__(self):
        logger.add("data/logs/grass.log", rotation="00:00", format="[{time:YYYY - MM - DD HH:mm:ss}] [{level}]: {message}")
        self.session_configs = None
        self.sessions = []
        self.health_monitor = None
        self.background_task = None

    def bootstrap(self):
        logger.info("grass多开助手程序启动,Grass限制收紧，请勿短时间内连续重复操作软件，启动时请耐心等待，如有问题请联系开发者！")
        dashboard.append_log("grass多开助手程序启动,Grass限制收紧，请勿短时间内连续重复操作软件，启动时请耐心等待，如有问题请联系开发者！")
        self.background_task = threading.Thread(target=self.start_event_loop, daemon=True)
        self.background_task.start()
        dashboard.show()

    @staticmethod
    def stop_loop_on_exception(loop, future):
        try:
            future.result()
        except Exception as e:
            loop.stop()
            logger.error(f"执行异常：{e}")

    def start_event_loop(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        future = loop.create_task(self.start_cut_grass())
        future.add_done_callback(partial(self.stop_loop_on_exception, loop))
        try:
            loop.run_forever()
        finally:
            loop.close()

    async def start_cut_grass(self):
        try:
            await self.load_grass_session_config()
            start_session_task = asyncio.create_task(self.start_grass_session())
            check_session_task = asyncio.create_task(self.start_health_monitor())
            generate_account_file_task = asyncio.create_task(utils.generate_account_file(self.session_configs))
            generate_device_id_file_task = asyncio.create_task(utils.generate_device_id_file(self.session_configs))
            grass_session_tasks = [start_session_task, check_session_task, generate_account_file_task, generate_device_id_file_task]
            await asyncio.gather(*grass_session_tasks)
        except Exception as e:
            logger.error(f"执行异常：{e}")

    async def load_grass_session_config(self):
        self.session_configs = utils.parse_proxy_config()
        if self.session_configs is None:
            dashboard.append_log(f"加载代理配置完成，共加载0条配置")
            logger.info(f"加载代理配置完成，共加载0条配置")
            return
        load_user_id_tasks = {}
        for session_config in self.session_configs:
            if session_config["user_id"] is not None or session_config["username"] in load_user_id_tasks :
                continue
            load_user_id_task = asyncio.create_task(self.load_session_user_id(
                    session_config["username"],
                    session_config["password"],
                    session_config["proxy_ip"],
                    session_config["proxy_port"],
                    session_config["proxy_username"],
                    session_config["proxy_password"]
                )
            )
            load_user_id_tasks[session_config["username"]] = load_user_id_task
        await asyncio.gather(*load_user_id_tasks.values())
        dashboard.append_log(f"加载代理配置完成，共加载{len(self.session_configs)}条配置")
        logger.info(f"加载代理配置完成，共加载{len(self.session_configs)}条配置")
        dashboard.init_table_row(self.session_configs)
    async def load_session_user_id(self, username, password, proxy_ip, proxy_port, proxy_username, proxy_password):
        try:
            user_info = await website.login(username, password, proxy_ip, proxy_port, proxy_username, proxy_password)
            logger.info(f"用户【{username}】登录获取信息成功:{user_info}")
            if user_info is None or user_info["userId"] is None:
                return
            for item in self.session_configs:
                if item["username"] != username:
                    continue
                item["user_id"] = user_info["userId"]
        except Exception as e:
            logger.error(f"用户【{username}】登录获取user_id异常:{e}")
    async def start_grass_session(self):
        connect_tasks = []
        for item in self.session_configs:
            s = Session(
                item["sid"],
                item["username"],
                item["username"],
                item["user_id"],
                item["device_id"],
                item["user_agent"],
                item["proxy_ip"],
                item["proxy_port"],
                item["proxy_username"],
                item["proxy_password"]
            )
            self.sessions.append(s)
            connect_tasks.append(s.connect())
        await asyncio.gather(*connect_tasks)
    async def start_health_monitor(self):
        while True:
            try:
                await asyncio.sleep(config.HEALTH_CHECK_INTERVAL)
                await self.health_check()
                await utils.check_is_not_allow_running()
            except Exception as e:
                logger.error(f"节点健康检查，出现异常:{e}")

    async def health_check(self):
        try:
            invalid_count = 0
            retry_count = 0
            for s in self.sessions:
                if s.status == "invalid":
                    invalid_count = invalid_count + 1
                    continue
                if s.is_healthy():
                    continue
                retry_count = retry_count + 1
                asyncio.create_task(s.connect())
            dashboard.append_log(f"节点健康检查,系统载入节点数{len(self.sessions)},无效节点数:{invalid_count},需要重连节点数{retry_count}")
            logger.info(f"节点健康检查,系统载入节点数{len(self.sessions)},无效节点数:{invalid_count},需要重连节点数{retry_count}")
        except Exception as e:
                logger.error(f"节点健康检查，出现异常:{e}")

grass_boot = Robot()
